﻿using System.Collections;
using Component.Mesh;
using Component.Track;
using Component.Trains;
using Component.UI.View;
using Tools;
using UnityEngine;

namespace Component.UI.Tools
{
    public class TransferClicker : MonoBehaviour
    {
        
        private Ray cursorRay;
        private bool newLine;
        private bool drawLine;
        private bool switchLineOver;
        private bool hadNewLine;
        private bool hadRemoveLine;
        private bool cameraMovable;
        private StationNode antherNode;
        private StationNode node;

        private int lineTag;
        
        [SerializeField] private float nodeWidth = 1;
        private float lineWidth = 1;
        private DrawLineTools drawingEndLine;
        private DrawLineTools currentLine;

        private GameView[] drawableUi;

        private void Awake()
        {
            drawableUi = gameObject.GetComponentsInChildren<GameView>();
        }

        private void Start()
        {
            lineWidth = nodeWidth / 4;
        }

        [SerializeField] private LayerMask nodeMask;
        private LineData tempLineData;

        private void Update()
        {
            cursorRay = CameraTools.ScreenRayHitInfo(Input.mousePosition);
                
            CameraTools.CameraZoom();
            OnGameObjectClick();
        }

        /// <summary>
        /// 鼠标点下、拖拽、鼠标抬起
        /// </summary>
        private void OnGameObjectClick()
        {
            if (cameraMovable)
            {
                CameraTools.DragCamera(delegate(bool dragover)
                {
                    cameraMovable = !dragover;
                });
                return;
            }
            
            if (Input.GetMouseButtonDown(0)) //鼠标点下
            {
                CheckDrawing();
            }
            else if(Input.GetMouseButtonUp(0))  //鼠标松开 确定此次拖拽操作的最终行为
            {
                //结束结点突出显示
                if (node != null)
                {
                    node.NodeHoverOver();
                }
                //检测到另一个点
                if (antherNode != null && (newLine || drawLine))
                {
                    antherNode.NodeHoverOver();
                    TransferTools.BeNotAvailable();
                    
                    //确认是否两点另一个是否可以联立直线，不能则清除当前拖拽的线，并绘制结束线
                    if (antherNode.doubleDrawable())
                    {
                        currentLine.Draw45TurnLine(node.transform.position, antherNode.transform.position, lineWidth, TransferTools.Color);
                        //先设置antherNode,再设置node是因为 有一种情况：当处于撤回操作又去连接新的结点的时候，node已经有了，而antherNode是一个新的
                        currentLine.SetNode(antherNode);
                        currentLine.SetNode(node);

                        antherNode.SetLine(currentLine);

                        //建立新的结点
                        CheckDrawNodeEndLine();
                        
                        //改变lineData
                        if (drawLine)
                        {
                            hadNewLine = true;
                            tempLineData = currentLine.LineData;
                        }
                    }
                    else
                    {
                        currentLine.ClearMesh();
                        Line.ResetLine(currentLine);
                        DrawLineTools line = Line.CreateEnd(node);
                        DrawNodeEndLine(line, node.EndDirection, node.transform.position, lineWidth, lineWidth * 4);
                    }

                    if (newLine)
                    {
                        if (drawableUi[0].CurrentCount > 1)
                        {
                            Train train = new Train(currentLine.LineData, currentLine.Color, node.EndDirection, delegate(TrainNode trainNode)
                            {
                                // Task updateTask = new Task(UpdateLineData(trainNode));
                            });
                            drawableUi[0].CurrentCount--;
                        }
                        
                    }
                    
                    
                    if (currentLine.gameObject.layer == 0)
                    {
                        currentLine.gameObject.layer = 9;
                    }
                    
                    antherNode = null;
                    node = null;
                }else if(newLine)
                {
                    currentLine.ClearMesh();
                    Line.ResetLine(currentLine);
                    node.ReplaceLine(currentLine, null);
                }else if (drawLine)
                {
                    currentLine.ClearMesh();
                    Line.ResetLine(currentLine);
                    
                    if (antherNode == null)
                    {
                        DrawLineTools endLine = node.GetLine(currentLine);
                        //回撤到结束线，所以颜色要重新激活
                        if (endLine != null && endLine.gameObject.layer == LayerMask.NameToLayer("End"))
                        {
                            endLine.ClearNode();
                            Line.ResetEndLine(endLine);
                            node.ClearLine();
                            TransferTools.BeAvailable(TransferTools.Color);
                        }
                        else
                        {
                            DrawLineTools line = Line.CreateEnd(node);
                            DrawNodeEndLine(line, node.EndDirection, node.transform.position, lineWidth, lineWidth * 4);
                            node.ReplaceLine(currentLine, line);
                        }
                    }
                }
                
                newLine = false;
                drawLine = false;
                node = null;
                antherNode = null;
                drawingEndLine = null;
                currentLine = null;
            }
            else  //鼠标拖曳
            {
                if (newLine)
                {
                    CheckOtherNode();
                    currentLine.Draw45TurnLine(node.transform.position, CameraTools.GetCursor(), lineWidth, TransferTools.Color);
                }

                if (drawLine)
                {
                    CheckOtherNode();
                    //如果选到自身节点，要做撤销操作获取当前节点的下一条线，再绘制线
                    if (antherNode == node)
                    {
                        //新拖拽出来的线
                        Line.ResetLine(currentLine);
                        
                        currentLine = antherNode.GetLine(currentLine, true);
                        
                        //虚线
                        DrawLineTools temp = currentLine;

                        currentLine = Line.CreateLine();
                        currentLine.CopyLine(temp);     //让新的线继承虚线的一些元素
                        
                        //让替换某段节点，并替换当前线
                        node = currentLine.GetNode(antherNode);
                        node.ReplaceLine(temp, currentLine);
                        
                        tempLineData = currentLine.LineData;
                        hadRemoveLine = true;

                        //清楚上一个与线的关系
                        currentLine.ReplaceNode(antherNode, null);
                        antherNode.ClearLine();

                        Line.ResetLine(temp);
                    }

                    if (node == null)
                    {
                        Debug.LogError("node is null");
                    }
                    if (currentLine == null)
                    {
                        Debug.LogError("current is null");
                    }
                    else
                    {
                        if (currentLine.gameObject.layer != 0)
                        {
                            currentLine.gameObject.layer = 0;
                        }
                        currentLine.Draw45TurnLine(node.transform.position, CameraTools.GetCursor(), lineWidth, TransferTools.Color);
                    }
                }
            }
        }
        /// <summary>
        /// 点击操作检测
        /// </summary>
        private void CheckDrawing()
        {
            if (!Physics.Raycast(cursorRay, out var hit))
            {
                cameraMovable = true;
                foreach (var ui in drawableUi)
                {
                    if (!ui.Clicking)
                    {
                        continue;
                    }
                    
                    cameraMovable = false;
                    break;
                }
                return;
            }
            //确认点击的操作
            //点击了结点
            if (hit.transform.gameObject.layer == LayerMask.NameToLayer("Node"))
            {
                node = hit.transform.GetComponent<StationNode>();
                //1.新建点线，并自动切换颜色
                if (TransferTools.SwitchColor())
                {
                    currentLine = Line.CreateLine();
                    node.SetLine(currentLine);
                    newLine = true;
                }
                
                node.NodeHover();
            }
            //点击了结束线,那么应该将结束线替换为一条新的直线
            if (hit.transform.gameObject.layer == LayerMask.NameToLayer("End"))
            { 
                drawingEndLine = hit.transform.GetComponent<DrawLineTools>();
                TransferTools.Color = drawingEndLine.Color;
                node = drawingEndLine.GetNode();
                currentLine = Line.CreateLine();
                node.ReplaceLine(drawingEndLine ,currentLine);
                drawLine = true;
                Line.ResetEndLine(drawingEndLine);
            }
        }
        /// <summary>
        /// 检测是否该绘制结束线
        /// </summary>
        private void CheckDrawNodeEndLine()
        {
            if (node.SingleDrawable())
            {
                DrawLineTools line = Line.CreateEnd(node);
                node.EndDirection = currentLine.StartPosDir();
                DrawNodeEndLine(line, node.EndDirection, node.transform.position, lineWidth, lineWidth * 4);
            }

            if (antherNode.SingleDrawable())
            {
                DrawLineTools line = Line.CreateEnd(antherNode);
                antherNode.EndDirection = currentLine.EndPosDir();
                DrawNodeEndLine(line,antherNode.EndDirection, antherNode.transform.position, lineWidth, lineWidth * 4);
            }
        }

        private void DrawNodeEndLine(DrawLineTools line, Vector3 direction, Vector3 original, float width, float height)
        {
            line.DrawEndNode(direction, original, width, height, TransferTools.Color);
        }
        /// <summary>
        /// 检测另一个点
        /// </summary>
        private void CheckOtherNode()
        {
            if (Physics.Raycast(cursorRay, out var hitInfo, Mathf.Infinity, LayerTools.NodeLayerMask))
            {
                antherNode = hitInfo.transform.GetComponent<StationNode>();
                
                if (antherNode != null)
                {

                    if (currentLine != null && antherNode.GetLine(currentLine)!= null && antherNode.GetLine(currentLine).gameObject.layer == LayerMask.NameToLayer("End"))
                    {
                        antherNode = null;
                        return;
                    }
                    
                    
                    antherNode.NodeHover();
                    
                    if (antherNode == node && drawingEndLine == null)
                    {
                        antherNode = null;
                    }
                }
            }else
            {
                if (antherNode != null)
                {
                    antherNode.NodeHoverOver();
                    antherNode = null;
                }
            }
        }

        private IEnumerator UpdateLineData(TrainNode train)
        {
            while (true)
            {
                if (tempLineData != null && train.Color == tempLineData.LineColor)
                {
                    if (hadNewLine)
                    {
                        // train.FollowLine += tempLineData;
                        train.AddLineData(tempLineData);
                        hadNewLine = false;
                    }

                    if (hadRemoveLine)
                    {
                        // train.FollowLine -= tempLineData;
                        train.RemoveLineData(tempLineData);
                        hadRemoveLine = false;
                    }
                }
                
                yield return new WaitForSeconds(.2f);
            }
        }
    }
}